/**
 *	\file
 *	\brief TODO complete the documentation of lexerTest.c
 *
 * 	\date Jul 28, 2013
 * 	\author koldar
 */

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include "main-tools.h"
#include "memory-tools.h"
#include "lexer.h"

//used to disable the implicit-function-declaration warning shwon on the call of yyparse()
#pragma GCC diagnostic ignored "-Wimplicit-function-declaration"

/**represents that this test is successful*/
#define TEST_SUCCESS 1
/**represents that this test is failed*/
#define TEST_FAILURE 0
/**represents that this test is skipped (cause is present in TESTSUITE_TESTEXCLUDED )*/
#define TEST_SKIPPED 2

/**represents the number of total tests in this suite, both included and excluded.*/
#define TESTSUITE_LENGTH 18
/**indicates a list of test IDs which won't be executed. Use commas (",") as separator*/
#define TESTSUITE_TESTEXCLUDED 0,1,2,3,4,5,6,7,8,9,10,11,12,13

#include "parser.h"
#include "lexer.h"
#include "parser-tools.h"

int (*testcase[TESTSUITE_LENGTH])(void);

/**Tests if yyparse() can be effectevely used
 *
 * @return true if it works, FALSE or Segmenetation fault if fails
 */
bool test00(){
	FILE* f=fopen("yaoola_src/lexer04_grouplabel.yaoola","r");
	int result;
	if (f==NULL){
		printf("source file not found");
		return false;
	}
	printf("yyin=file\n");
	yylex_destroy();
	yyrestart(f);
	yyset_in(f);
	printf("building tree...\n");
	result=yyparse();
	printf("tree read.\n");
	fclose(f);
	return result==0;
}

/**Tests:
 * \li memory leak in yyparse();
 * \li testing in freeSyntaxTree();
 * \li true avability of the variable root in parser.y;
 *
 * @return TRUE if there getMemoryAllocation() returns 0
 */
bool test01(){
	initLibrary();
	FILE* f=fopen("yaoola_src/lexer04_grouplabel.yaoola","r");
	int result;
	extern PSyntaxNode root;
	if (f==NULL){
		printf("source file not found");
		return false;
	}
	printf("setting yylex...");
	yylex_destroy();
	yyrestart(f);
	yyset_in(f);
	printf("Initial memory used: %d\n",getMemoryAllocated());
	printf("building tree...\n");
	result=yyparse();
	if (result!=0){
		printf("tree not read.\n");
		return false;
	}
	printf("tree read.\n");
	printf("Syntax Tree size: %d\n",getMemoryAllocated());
	printf("freeing...\n");
	freeSyntaxTree(root);
	fclose(f);
	printf("memory leak: %d\n",getMemoryAllocated());
	if (getMemoryAllocated()==0){
		return true;
	}
	return false;
}

/**tests:
 * 	\li buildSyntaxTreeGraph() function;
 *
 * @return
 */
bool test02(){
	FILE* f=fopen("yaoola_src/lexer04_grouplabel.yaoola","r");
	int result;
	bool testresult;
	extern PSyntaxNode root;
	if (f==NULL){
		printf("source file not found");
		return false;
	}
	printf("setting yylex...");
	yylex_destroy();
	yyrestart(f);
	yyset_in(f);
	printf("Initial memory used: %d\n",getMemoryAllocated());
	printf("building tree...\n");
	result=yyparse();
	if (result!=0){
		printf("tree not read.\n");
		return false;
	}
	printf("testing buildSyntaxTreeGraph(\"graph01\",root,false,false)...\n");
	testresult=buildSyntaxTreeGraph("test02_graph01",root,false,false);
	if (testresult==false){
		return false;
	}
	printf("testing buildSyntaxTreeGraph(\"graph02\",root,true,false)...\n");
	testresult=buildSyntaxTreeGraph("test02_graph02",root,true,false);
	if (testresult==false){
		return false;
	}
	printf("testing buildSyntaxTreeGraph(\"graph03\",root,true,true)...\n");
	testresult=buildSyntaxTreeGraph("test02_graph03",root,true,true);
	if (testresult==false){
		return false;
	}
	freeSyntaxTree(root);
	return true;
}

/**tests a simple class where:
 * 	\li no require clause is present
 * 	\li no field resources are present
 * 	\li no function resources are present
 *
 * @return TRUE if the parser executes it without segmentation fault
 */
bool test03(){
	FILE* f=fopen("yaoola_src/parser_test03.yaoola","r");
	int result;
	extern PSyntaxNode root;
	if (f==NULL){
		printf("source file not found");
		return false;
	}
	printf("setting yylex...");
	yylex_destroy();
	yyrestart(f);
	yyset_in(f);
	printf("building tree...\n");
	result=yyparse();
	if (result!=0){
		printf("tree not read.\n");
		return false;
	}
	if (root==NULL){
		printf("root NULL.\n");
		return false;
	}
	buildSyntaxTreeGraph("parser_test03",root,true,true);
	freeSyntaxTree(root);
	return true;
}

/**tests if parser can detect this error:
 * \code
 *  class static abstract const Result extends Object,AbastractFactory, member of UNIVERSITY,VAULT_BULLIES, UNIVERSITY_SECRETS
 * \endcode
 *
 * @return TRUE if syntax error is detected
 */
bool test04(){
	FILE* f=fopen("yaoola_src/parser0_test04.yaoola","r");
	int result;
	extern PSyntaxNode root;

	if (f==NULL){
		printf("source file not found");
		return false;
	}
	printf("setting yylex...");
	yylex_destroy();
	yyrestart(f);
	yyset_in(f);


	printf("building tree...\n");
	result=yyparse();

	if (result!=0){
		printf("tree not read.\n");
		return true;
	}
	return false;
}

/**tests a source file where:
 * 	\li grouplabel sector is present
 * 	\li class definition is present
 * 	\li the class does not contain any resource
 *
 * @return TRUE if there is no segmentation fault
 */
bool test05(){
	FILE* f=fopen("yaoola_src/parser_test05.yaoola","r");
	int result;
	extern PSyntaxNode root;
	if (f==NULL){
		printf("source file not found");
		return false;
	}
	printf("setting yylex...\n");
	yylex_destroy();
	yyrestart(f);
	yyset_in(f);
	printf("building tree...\n");
	result=yyparse();
	if (result!=0){
		printf("tree not read.\n");
		return false;
	}
	buildSyntaxTreeGraph("parser_test05",root,true,true);
	freeSyntaxTree(root);
	return true;
}

/**tests a file where:
 * \li require sector is present
 * \li class sector is present
 * \li in the class there are only reference / value of simple/class type. Not array involved
 *
 * @return
 */
bool test06(){
	FILE* f=fopen("yaoola_src/parser_test06.yaoola","r");
	int result;
	extern PSyntaxNode root;
	if (f==NULL){
		printf("source file not found");
		return false;
	}
	printf("setting yylex...\n");
	yylex_destroy();
	yyrestart(f);
	yyset_in(f);
	printf("building tree...\n");
	result=yyparse();
	if (result!=0){
		printf("tree not read.\n");
		return false;
	}
	buildSyntaxTreeGraph("parser_test06",root,true,true);
	freeSyntaxTree(root);
	return true;
}
/**tests a source file where:
 * 	\li require sector is present;
 * 	\li class sector is present;
 * 	\li no method declared;
 * 	\li field declared;
 * 	\li use of static and consrt
 * 	\li use of implicit value of
 * 	\li use of reference of
 * 	\li use of simple type, array type and class type;
 * 	\li label and special label mixed;
 *
 * @return
 */
bool test07(){
	FILE* f=fopen("yaoola_src/parser_test07.yaoola","r");
	int result;
	extern PSyntaxNode root;
	if (f==NULL){
		printf("source file not found");
		return false;
	}
	printf("setting yylex...\n");
	yylex_destroy();
	yyrestart(f);
	yyset_in(f);
	printf("building tree...\n");
	result=yyparse();
	if (result!=0){
		printf("tree not read.\n");
		return false;
	}
	buildSyntaxTreeGraph("parser_test07",root,true,true);
	freeSyntaxTree(root);
	return true;
}
/**test a source file where:
 *	\li a require sector is present;
 *	\li a field declaration is present;
 *	\li a method declaration is present (but no body is specified)
 *
 * @return TRUE is method declaration works corretly and there are no memory leaks
 */
bool test08(){
	FILE* f=fopen("yaoola_src/parser_test08.yaoola","r");
	int result;
	extern PSyntaxNode root;
	if (f==NULL){
		printf("source file not found");
		return false;
	}
	printf("setting yylex...\n");
	yylex_destroy();
	yyrestart(f);
	yyset_in(f);
	initLibrary();
	printf("building tree...\n");
	result=yyparse();
	if (result!=0){
		printf("tree not read.\n");
		return false;
	}
	buildSyntaxTreeGraph("parser_test08",root,true,true);
	freeSyntaxTree(root);
	return getMemoryAllocated()==0;
}

/**tests a source file where:
 * \li a require sector is present;
 * \li a field declaration is present;
 * \li a method delcaration is present;
 * \li mthod boies are presents;
 *
 * the method bodies include stats:
 * \li procedure call;
 * \li assignment;
 * \li expr evaluation;
 * \li return stat;
 *
 * @return TRUE is there is no memory leak
 */
bool test09(){
	FILE* f=fopen("yaoola_src/parser_test09.yaoola","r");
	int result;
	extern PSyntaxNode root;
	if (f==NULL){
		printf("source file not found");
		return false;
	}
	printf("setting yylex...\n");
	yylex_destroy();
	yyrestart(f);
	yyset_in(f);
	initLibrary();
	printf("building tree...\n");
	result=yyparse();
	if (result!=0){
		printf("tree not read.\n");
		return false;
	}
	buildSyntaxTreeGraph("parser_test09",root,true,true);
	freeSyntaxTree(root);
	return getMemoryAllocated()==0;
}

/**tests a source file where:
 *  \li if then elsif else is present
 *
 * @return TRUE is there is no memory leak
 */
bool test10(){
	FILE* f=fopen("yaoola_src/parser_test10.yaoola","r");
	int result;
	extern PSyntaxNode root;
	if (f==NULL){
		printf("source file not found");
		return false;
	}
	printf("setting yylex...\n");
	yylex_destroy();
	yyrestart(f);
	yyset_in(f);
	initLibrary();
	printf("building tree...\n");
	result=yyparse();
	if (result!=0){
		printf("tree not read.\n");
		return false;
	}
	result=buildSyntaxTreeGraph("parser_test10",root,true,true);
	if (result==false){
		printf("graph failure.\n");
		return false;
	}
	freeSyntaxTree(root);
	return getMemoryAllocated()==0;
}

/**tests a source file where:
 *
 * \li while stat is present
 * \li there a no nested loops
 *
 * @return TRUE if there is no memory leak
 */
bool test11(){
	FILE* f=fopen("yaoola_src/parser_test11.yaoola","r");
	int result;
	extern PSyntaxNode root;
	if (f==NULL){
		printf("source file not found");
		return false;
	}
	printf("setting yylex...\n");
	yylex_destroy();
	yyrestart(f);
	yyset_in(f);
	printf("building tree...\n");
	result=yyparse();
	if (result!=0){
		printf("tree not read.\n");
		return false;
	}
	result=buildSyntaxTreeGraph("parser_test11",root,true,true);
	if (result==false){
		printf("graph failure.\n");
		return false;
	}
	freeSyntaxTree(root);
	return getMemoryAllocated()==0;
}

/**tests a source file where:
 *
 * \li do while stat is present
 * \li there a no nested loops
 *
 * @return TRUE if there is no memory leak
 */
bool test12(){
	FILE* f=fopen("yaoola_src/parser_test12.yaoola","r");
	int result;
	extern PSyntaxNode root;
	if (f==NULL){
		printf("source file not found");
		return false;
	}
	printf("setting yylex...\n");
	yylex_destroy();
	yyset_in(f);
	yyrestart(f);
	initLibrary();
	printf("building tree...\n");
	result=yyparse();
	if (result!=0){
		printf("tree not read.\n");
		return false;
	}
	result=buildSyntaxTreeGraph("parser_test12",root,true,true);
	if (result==false){
		printf("graph failure.\n");
		return false;
	}
	freeSyntaxTree(root);
	return getMemoryAllocated()==0;
}

/**test a file where:
 * \li while loop and do ... while loops are nested together
 *
 * @return TRUE if there is no segmentation fault
 */
bool test13(){
	FILE* f=fopen("yaoola_src/parser_test13.yaoola","r");
	int result;
	extern PSyntaxNode root;
	if (f==NULL){
		printf("source file not found");
		return false;
	}
	printf("setting yylex...\n");
	yylex_destroy();
	yyrestart(f);
	yyset_in(f);
	initLibrary();
	printf("building tree...\n");
	result=yyparse();
	if (result!=0){
		printf("tree not read.\n");
		return false;
	}
	result=buildSyntaxTreeGraph("parser_test13",root,true,true);
	if (result==false){
		printf("graph failure.\n");
		return false;
	}
	freeSyntaxTree(root);
	return getMemoryAllocated()==0;
}

/**test a file where:
 * \li for loop is present
 * \li no other loops are present
 *
 * @return TRUE if there is no memory leak
 */
bool test14(){
	FILE* f=fopen("yaoola_src/parser_test14.yaoola","r");
	int result;
	extern PSyntaxNode root;
	if (f==NULL){
		printf("source file not found");
		return false;
	}
	printf("setting yylex...\n");
	yylex_destroy();
	yyrestart(f);
	yyset_in(f);
	initLibrary();
	printf("building tree...\n");
	result=yyparse();
	if (result!=0){
		printf("tree not read.\n");
		return false;
	}
	result=buildSyntaxTreeGraph("parser_test14",root,true,true);
	if (result==false){
		printf("graph failure.\n");
		return false;
	}
	freeSyntaxTree(root);
	return getMemoryAllocated()==0;
}

/**test a file where:
 * \li switch clause
 * \li default condition is present
 * \li some case are present
 * \li break is ppresent
 *
 * @return TRUE if there is no memory leak
 */
bool test15(){
	FILE* f=fopen("yaoola_src/parser_test15.yaoola","r");
	int result;
	extern PSyntaxNode root;
	if (f==NULL){
		printf("source file not found");
		return false;
	}
	printf("setting yylex...\n");
	yylex_destroy();
	yyrestart(f);
	yyset_in(f);
	initLibrary();
	printf("building tree...\n");
	result=yyparse();
	if (result!=0){
		printf("tree not read.\n");
		return false;
	}
	result=buildSyntaxTreeGraph("parser_test15",root,true,true);
	if (result==false){
		printf("graph failure.\n");
		return false;
	}
	freeSyntaxTree(root);
	return getMemoryAllocated()==0;
}

/**test a big file where:
 *
 * @return TRUE if there is no memory leak
 */
bool test16(){
	FILE* f=fopen("yaoola_src/parser_test16.yaoola","r");
	int result;
	extern PSyntaxNode root;
	if (f==NULL){
		printf("source file not found");
		return false;
	}
	printf("setting yylex...\n");
	yylex_destroy();
	yyrestart(f);
	yyset_in(f);
	initLibrary();
	printf("Initial memory used: %d\n",getMemoryAllocated());
	printf("building tree...\n");
	result=yyparse();
	if (result!=0){
		printf("tree not read.\n");
		return false;
	}
	result=buildSyntaxTreeGraph("parser_test16",root,true,true);
	if (result==false){
		printf("graph failure.\n");
		return false;
	}
	printf("before free memory leak: %d\n",getMemoryAllocated());
	freeSyntaxTree(root);
	printf("after free memory leak: %d\n",getMemoryAllocated());
	return getMemoryAllocated()==0;
}

/**tests a source file where:
 *
 * \li a simple local variable declation is present
 * \li the type of the variable is actually a class
 *
 * @return TRUE if there is no memory leak
 */
bool test17(){
	FILE* f=fopen("yaoola_src/parser_test17.yaoola","r");
	int result;
	extern PSyntaxNode root;
	if (f==NULL){
		printf("source file not found");
		return false;
	}
	printf("setting yylex...\n");
	yylex_destroy();
	yyset_in(f);
	yyrestart(f);
	initLibrary();
	printf("building tree...\n");
	result=yyparse();
	if (result!=0){
		printf("tree not read.\n");
		return false;
	}
	result=buildSyntaxTreeGraph("parser_test17",root,true,true);
	if (result==false){
		printf("graph failure.\n");
		return false;
	}
	freeSyntaxTree(root);
	return getMemoryAllocated()==0;
}

bool setUp(){
	/* ************** TESTCASE Construction ***********************/
	testcase[0]=(void*)test00;
	testcase[1]=(void*)test01;
	testcase[2]=(void*)test02;
	testcase[3]=(void*)test03;
	testcase[4]=(void*)test04;
	testcase[5]=(void*)test05;
	testcase[6]=(void*)test06;
	testcase[7]=(void*)test07;
	testcase[8]=(void*)test08;
	testcase[9]=(void*)test09;
	testcase[10]=(void*)test10;
	testcase[11]=(void*)test11;
	testcase[12]=(void*)test12;
	testcase[13]=(void*)test13;
	testcase[14]=(void*)test14;
	testcase[15]=(void*)test15;
	testcase[16]=(void*)test16;
	testcase[17]=(void*)test17;
	/* ************ OTHER ******************/
	return true;
}

bool tearDown(){
	return true;
}

int main(){
	if (setUp()==false){
		printf("SETUP FAILED.\n");
		return EXIT_FAILURE;
	}
	printf("SETUP SUCCESSFUL\n");

	int i,j;
	int excluded[]={TESTSUITE_TESTEXCLUDED};
	int testResults[TESTSUITE_LENGTH];
	int failed_tests=0;
	bool toskip;

	for(i=0;i<TESTSUITE_LENGTH;i++){
		//check if the test ID i is present in the excluded array. If it is the test must be skipped
		toskip=false;
		for (j=0;j<(sizeof(excluded)/sizeof(excluded[0]));j++){
			if(excluded[j]==i){
				toskip=true;
				break;
			}
		}
		if (toskip==true){
			testResults[i]=TEST_SKIPPED;
			continue;
		}
		printf("############# Running now test case %d ##############\n",i);
		testResults[i]=(*testcase[i])();
		if (testResults[i]==true){
			printf("Test case #%d successful.\n",i);
		}else{
			printf("Test case #%d failed.\n",i);
			failed_tests++;
		}
	}

	printf("####################################################\n");
	if (tearDown()==false){
		printf("TEAR DOWN FAILED.\n");
		return EXIT_FAILURE;
	}
	printf("TEAR DOWN SUCCESSFUL.\n");
	printf("-------------------------------------------\n");
	printf("Summary of this suite:\n");
	for (i=0;i<TESTSUITE_LENGTH;i++){
		printf("Test #%d: ",i);
		switch (testResults[i]){
		case TEST_SUCCESS: {
			printf("success");
			break;
		}
		case TEST_FAILURE: {
			printf("failure");
			break;
		}
		case TEST_SKIPPED: {
			printf("skipped");
			break;
		}
		default: {
			printf("??? (%d)",testResults[i]);
			break;
		}
		}
		printf("\n");
	}
	printf("number of test failed: %d\n",failed_tests);
	printf("--------------------------------\n");
	printf("TEST SUITE FINISHED\n");
	return EXIT_SUCCESS;
}
